{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3 数据容器 —— Numpy\n",
    "\n",
    "  数据分析往往都是对多个二维表，或者多个多维数据进行分析。因此，传统的单变量很难胜任。Python内置的list、dict等数据类型，执行效率低也不适合。Pyhton在进行数据分析时常用的数据容器有：\n",
    "  - Numpy\n",
    "  - Pandas\n",
    "  - Tensor\n",
    "\n",
    "Numpy是用来处理数组的，Pandas相当于我们平常接触的excel表格，但更灵活。Tensor相当于多维数组。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.1 什么是Numpy\n",
    "- 高级版list：索引方式、数据处理上的升级\n",
    "- Numpy数组的数据类型是统一的，不同类型的数据不能混装在一起\n",
    "\n",
    "为什么不可以使用Python自带的List来处理数组呢，主要是因为以下两点原因：\n",
    "\n",
    " - **处理数组更快**：NumPy和Pandas的底层逻辑是用C语言写的，C这种底层语言自然能更快更有效率地调用电脑资源。\n",
    " - **处理数组更灵活**：NumPy 库中提供更多处理 Array 的方式，比如合并分割数组、对数组进行统计计算等等。\n",
    "  \n",
    "  总而言之，NumPy使用了更优秀的实现方式来处理数组，和Python自带的数据类型相比，NumPy能用更少的空间存储相同的数据量，并用更快的方式进行数组计算。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.2 新建Numpy数组\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "a = np.array([1,2,3,4,5])\n",
    "a\n",
    "# 一维的数组也叫向量\n",
    "b = np.array([[1,2,3],\n",
    "              [4,5,6],\n",
    "              [7,8,9]])\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 在实际的数据分析中，数据一般来源于外部数据文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2., 3.],\n",
       "       [4., 5., 6.],\n",
       "       [7., 8., 9.]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 读写文本文件\n",
    "cc = np.loadtxt('../data/3-1_save_data.txt',delimiter=',')\n",
    "cc\n",
    "# np.savetxt('../data/3-1_save_data.txt', b, fmt='%.2f', delimiter=',')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2., 3.],\n",
       "       [4., 5., 6.],\n",
       "       [7., 8., 9.]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 读写二进制文件（.npy）\n",
    "\n",
    "np.save('../data/3-1_save_data.npy',cc)\n",
    "\n",
    "dd = np.load('../data/3-1_save_data.npy')\n",
    "dd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.3 Numpy数组索引与切片\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[100 101 102 103 104 105 106 107 108 109]\n",
      "-----------------------------------------\n",
      "[102 103 104]\n",
      "[100 101 102 103 104]\n",
      "[100 101 102 103 104 105 106]\n",
      "[103 104 105 106 107 108]\n",
      "[103 104 105 106]\n",
      "[109 108 107 106 105 104 103 102 101 100]\n",
      "[102 105]\n",
      "[107 106 105 104]\n",
      "[100 102 104]\n",
      "[106 107 108 109]\n"
     ]
    }
   ],
   "source": [
    "# 一维数组（也称为向量）的索引\n",
    "\n",
    "array = np.arange(100,110) # [0 1 2 3 4 5 6 7 8 9]\n",
    "print(array)\n",
    "print('-----------------------------------------')\n",
    "\n",
    "print(array[2:5]) # 第3个元素到第5个元素（不包括第五个元素） [2 3 4],数组切片\n",
    "print(array[:5]) # 第1个元素到第5个元素 [0 1 2 3 4]\n",
    "print(array[:-3]) # 第1个元素到倒数第4个元素（不包括倒数第3个元素） [0 1 2 3 4 5 6]\n",
    "print(array[3:-1]) # 第4个元素到倒数第2个元素（不包括倒数第1个元素）[3 4 5 6 7 8]\n",
    "print(array[3:-3]) # 第4个元素到倒数第4个元素 [3 4 5 6]\n",
    "print(array[::-1]) # 颠倒NumPy的数组 [9 8 7 6 5 4 3 2 1 0]\n",
    "print(array[2:7:3]) # 从第3个元素到7个元素（不包括第7个元素），间隔为3 [2 5]\n",
    "print(array[-3:3:-1]) # 从倒数第3个元素（7），到第5个元素（4），回跳一个位置 [7 6 5 4]\n",
    "print(array[[0,2,4]]) #花式索引，用一个自然数数组索引另一个数组\n",
    "print(array[array>105])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4]\n",
      " [ 5  6  7  8  9]\n",
      " [10 11 12 13 14]\n",
      " [15 16 17 18 19]]\n",
      "------------------------------------------------\n",
      "3\n",
      "[10 11 12 13 14]\n",
      "[ 2  7 12 17]\n",
      "[[ 7  8]\n",
      " [12 13]]\n"
     ]
    }
   ],
   "source": [
    "# 二维数组索引\n",
    "matrix_1 = np.arange(20).reshape(4, 5) # 创建一个 4 * 5 的矩阵，取值范围在 0~19\n",
    "print(matrix_1)\n",
    "print('------------------------------------------------')\n",
    "print(matrix_1[0, 3]) # 第1行第4列的元素：3\n",
    "print(matrix_1[2, :]) # 第3行的所有元素 [10 11 12 13 14]\n",
    "print(matrix_1[:, 2]) # 第3列的所有元素 [ 2  7 12 17]\n",
    "print(matrix_1[1:3, 2:4]) # 第2行到第3行，第3列到第4列的子矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加法: [5 7 9]\n",
      "减法: [-3 -3 -3]\n",
      "乘法 (元素级): [ 4 10 18]\n",
      "除法 (元素级): [0.25 0.4  0.5 ]\n",
      "点积: 32\n",
      "矩阵乘法: [[19 22]\n",
      " [43 50]]\n",
      "数组 a 的和: 6\n",
      "数组 a 的平均值: 2.0\n",
      "数组 a 的最大值: 3\n",
      "数组 a 的最小值: 1\n"
     ]
    }
   ],
   "source": [
    "## 3.4 Numpy数组运算\n",
    "\n",
    "import numpy as np  \n",
    "\n",
    "# 创建两个数组  \n",
    "a = np.array([1, 2, 3])  \n",
    "b = np.array([4, 5, 6])  \n",
    "\n",
    "# 加法  \n",
    "print(\"加法:\", a + b)  \n",
    "\n",
    "# 减法  \n",
    "print(\"减法:\", a - b)  \n",
    "\n",
    "# 乘法 (元素级)  \n",
    "print(\"乘法 (元素级):\", a * b)  \n",
    "\n",
    "# 除法 (元素级)  \n",
    "print(\"除法 (元素级):\", a / b)  \n",
    "\n",
    "# 点积  \n",
    "print(\"点积:\", np.dot(a, b))  \n",
    "\n",
    "# 矩阵乘法 (如果 a 和 b 是矩阵)  \n",
    "a_matrix = np.array([[1, 2], [3, 4]])  \n",
    "b_matrix = np.array([[5, 6], [7, 8]])  \n",
    "print(\"矩阵乘法:\", np.matmul(a_matrix, b_matrix))  \n",
    "\n",
    "# 求和  \n",
    "print(\"数组 a 的和:\", np.sum(a))  \n",
    "\n",
    "# 平均值  \n",
    "print(\"数组 a 的平均值:\", np.mean(a))  \n",
    "\n",
    "# 最大值  \n",
    "print(\"数组 a 的最大值:\", np.max(a))  \n",
    "\n",
    "# 最小值  \n",
    "print(\"数组 a 的最小值:\", np.min(a))  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.5 Numpy数组的合并、分割和广播运算机制"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4 5 6]\n",
      "[2 3 2]\n",
      "两个矩阵相乘\n",
      "[ 8 15 12]\n",
      "\n",
      "矩阵与单个值得广播式运算\n",
      "[14 15 16]\n"
     ]
    }
   ],
   "source": [
    "c = np.array([2,3,2])\n",
    "print(b)\n",
    "print(c)\n",
    "print('两个矩阵相乘')\n",
    "print(b*c)\n",
    "print('\\n矩阵与单个值得广播式运算')\n",
    "print(b+10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.6 Numpy集合运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x的唯一值（unique）:  [1 2 3 4 5 6]\n",
      "x和y的交集： [2 3 4]\n",
      "x和y的并集： [1 2 3 4 5 6 9]\n",
      "x和y的差集： [1 5 6]\n",
      "y元素是否存在于x中： [ True  True  True  True  True  True  True False]\n"
     ]
    }
   ],
   "source": [
    "x = np.array([1,2,3,4,5,6,6,6,6,5])\n",
    "y = np.array([2,3,4,4,3,3,3,9])\n",
    "\n",
    "# 求唯一值值\n",
    "print('x的唯一值（unique）: ', np.unique(x))\n",
    "\n",
    "# 求交集，函数结尾是1d，一维\n",
    "print('x和y的交集：', np.intersect1d(x,y))\n",
    "\n",
    "# 求并集\n",
    "print('x和y的并集：', np.union1d(x,y))\n",
    "\n",
    "# 求差集\n",
    "print('x和y的差集：', np.setdiff1d(x,y))\n",
    "\n",
    "# 判断y的元素在x中是否存在\n",
    "print('y元素是否存在于x中：', np.in1d(y,x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Numpy数组的维度(ndim)          ： 2\n",
      "Numpy数组的形状(shape)         ： (3, 3)\n",
      "Numpy数组元素个数(ndim)        ： 9\n",
      "Numpy数组数据类型(dtype)       ： 9\n",
      "Numpy数组元素字节大小(itemsize)： 9\n"
     ]
    }
   ],
   "source": [
    "### 2.4.2 Numpy数组属性\n",
    "\n",
    "print('Numpy数组的维度(ndim)          ：', b.ndim)\n",
    "print('Numpy数组的形状(shape)         ：', b.shape)\n",
    "print('Numpy数组元素个数(ndim)        ：', b.size)\n",
    "print('Numpy数组数据类型(dtype)       ：', b.size)\n",
    "print('Numpy数组元素字节大小(itemsize)：', b.size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 读写数据文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np  \n",
    "\n",
    "# 创建一个数组  \n",
    "data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  \n",
    "\n",
    "# 将数组保存到 CSV 文件  \n",
    "np.savetxt('data.csv', data, delimiter=',')  \n",
    "\n",
    "# 从 CSV 文件读取数据  \n",
    "loaded_data = np.loadtxt('data.csv', delimiter=',')  \n",
    "print(\"从 CSV 文件读取的数据:\\n\", loaded_data)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 创建一个数组  \n",
    "data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  \n",
    "\n",
    "# 将数组保存到 Pickle 文件  \n",
    "np.save('data.npy', data)  \n",
    "\n",
    "# 从 Pickle 文件读取数据  \n",
    "loaded_data = np.load('data.npy')  \n",
    "print(\"从 Pickle 文件读取的数据:\\n\", loaded_data)  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
